package cn.com.dcsgo.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 使用环绕通知模拟事务
 *
 * @author Dcsgo
 * @since 2025/2/6 15:50
 */
@Aspect
@Component
@Order(1)
public class AroundTxAdvice {
    /**
     * 环绕通知与其他通知最大的不同是多了一个对目标方法执行的控制
     * 除此之外，对于可增强的代码功能与其他几个通知类似，通常采用try catch的结构
     * 来提供类似其他几个通知的功能
     *
     * @param proceedingJoinPoint 环绕通知获取连接点信息的参数
     * @return 目标方法返回的结果
     */
    @Around("cn.com.dcsgo.pointcut.RefPointCut.allService()")
    public Object advice(ProceedingJoinPoint proceedingJoinPoint) {
        Object[] args = proceedingJoinPoint.getArgs();
        try {
            //前置
            System.out.println("事务开启");
            //保证目标类的方法被执行，并返回结果
            Object result = proceedingJoinPoint.proceed(args);
            //后置
            System.out.println("事务提交");
            return result;
        } catch (Throwable e) {
            //异常
            System.out.println("事务回滚");
            //如果此处不将异常抛出，则调用者无法捕获到异常
            throw new RuntimeException(e);
        } finally {
            //最后
            System.out.println("处理完成");
        }
    }
}
